#include "StdAfx.h"
#include "deadZ80.h"
#include "opcodes.h"

CDeadZ80::CDeadZ80()
{
}

CDeadZ80::~CDeadZ80()
{
}

void CDeadZ80::Init()
{
	int i;
	
	for(i=0;i<Z80_PAGE_NUM;i++) {
		readpages[i] = writepages[i] = 0;
	}
}

void CDeadZ80::Reset()
{
	cycles = 0;			//reset cycle counter
	halt = 0;				//clear halt flag
	intmode = 0;
	inside_irq = 0;

	regs = &alt;
	AF = 0xFFFF;
	BC = 0xFFFF;
	DE = 0xFFFF;
	HL = 0xFFFF;

	regs = &main;
	AF = 0xFFFF;
	BC = 0xFFFF;
	DE = 0xFFFF;
	HL = 0xFFFF;

	sp = 0xFFFF;

	pc = 0;				//reset pc
}

void CDeadZ80::NMI()
{
	iff2 = iff1;
	iff1 = 0;
	WriteMemory8(--sp,(pc >> 8) & 0xFF);
	WriteMemory8(--sp,pc & 0xFF);
	pc = 0x0066;
	cycles += 11;
}

void CDeadZ80::IRQ()
{
	if(iff1 == 0)
		return;

	if(halt) {
		halt = 0;
		pc++;
	}

	switch(intmode) {
		case 0:
			inside_irq = 1;
			Step();
			break;
		case 1:
			WriteMemory8(--sp,(pc >> 8) & 0xFF);
			WriteMemory8(--sp,(pc >> 0) & 0xFF);
			pc = 0x0038;
			cycles += 13;
			break;
		case 2:
			message("im 2 not done\n");
			break;
		default:
			message("bad im\n");
			break;
	}
}

u32 CDeadZ80::Execute(u32 c)
{
	unsigned long start = cycles;
	unsigned long end = cycles + c;

	while(cycles < end) {
		if(Step() > 0)
			return(BAD_OPCODE);
	}
	return(end - start);
}



//step function goes here



unsigned char CDeadZ80::ReadMemory8(unsigned long addr)
{
//	printf("reading from $%04X\n",addr);
	if(readpages[addr >> Z80_PAGE_SHIFT])
		return(readpages[addr >> Z80_PAGE_SHIFT][addr & Z80_PAGE_MASK]);
	else if(readfuncs[addr >> Z80_PAGE_SHIFT])
		return(readfuncs[addr >> Z80_PAGE_SHIFT](user,addr));
	message("read not handled: $%04X\n",addr);
	return(0);
}

unsigned short CDeadZ80::ReadMemory16(unsigned long addr)
{
	return(ReadMemory8(addr) | (ReadMemory8(addr+1) << 8));
}

void CDeadZ80::WriteMemory8(unsigned long addr,unsigned char data)
{
//	printf("writing to $%04X = $%02X\n",addr,data);
	if(writepages[addr >> Z80_PAGE_SHIFT])
		writepages[addr >> Z80_PAGE_SHIFT][addr & Z80_PAGE_MASK] = data;
	else if(writefuncs[addr >> Z80_PAGE_SHIFT])
		writefuncs[addr >> Z80_PAGE_SHIFT](user,addr,data);
	else
		message("write not handled: $%04X = $%02X\n",addr,data);
}

void CDeadZ80::WriteMemory16(unsigned long addr,unsigned short data)
{
	WriteMemory8(addr,data & 0xFF);
	WriteMemory8(addr+1,(data >> 8) & 0xFF);
}

u32 CDeadZ80::GetPC()
{
	return(pc);
}

u32 CDeadZ80::GetCycle()
{
	return(cycles);
}

void CDeadZ80::SetIORead(TReadFunc *r)
{
	ioreadfunc = r;
}

void CDeadZ80::SetIOWrite(TWriteFunc *w)
{
	iowritefunc = w;
}

void CDeadZ80::SetRead(int p,TReadFunc *r)
{
	readfuncs[p] = r;
}

void CDeadZ80::SetWrite(int p,TWriteFunc *w)
{
	writefuncs[p] = w;
}

void CDeadZ80::SetIRQ(TIRQFunc *i)
{
	irqfunc = i;
}

void CDeadZ80::SetUser(void *u)
{
	user = u;
}

void CDeadZ80::SetReadPage(int p,u8 *d)
{
	readpages[p] = d;
}

void CDeadZ80::SetWritePage(int p,u8 *d)
{
	writepages[p] = d;
}

void CDeadZ80::SetPage(int p,u8 *d)
{
	SetReadPage(p,d);
	SetWritePage(p,d);
}
